初步打造一站式设计协作平台
sketch目录结构简介:
images目录为sketch文件内的图片素材资源;
pages目录下的json文件,为各个画板下图层属性的数据定义部分;
previews, text-previews用于操作系统内快速预览使用;
document.json 定义了画板层级结构、控件部分等信息;
meta.json 定义了操作记录、依赖字体、sketch版本等信息。
export const TextAlignmentMap = {
left: 0, // Visually left aligned
right: 1, // Visually right aligned
center: 2, // Visually centered
justified: 3, // Fully-justified. The last line in a paragraph is natural-aligned.
natural: 4 // Indicates the default alignment for script
}
export const TextAlignmentReverseMap = {
0: 'left', // Visually left aligned
1: 'right', // Visually right aligned
2: 'center', // Visually centered
3: 'justified', // Fully-justified. The last line in a paragraph is natural-aligned.
4: 'left' // Indicates the default alignment for script
}
export const VerticalTextAlignmentMap = {
top: 0, // Visually top aligned
middle: 1, // Visually centered
bottom: 2 // Visually bottom aligned
}
export const VerticalTextAlignmentReverseMap = {
0: 'top', // Visually top aligned
1: 'middle', // Visually centered
2: 'bottom' // Visually bottom aligned
}
/**
* 参考文档
* https://github.com/jonathantneal/css-font-weight-names
* https://www.w3.org/TR/css-fonts-3/#font-weight-prop
* https://bigelowandholmes.typepad.com/bigelow-holmes/2015/07/on-font-weight.html
*/
export const FontWeightMap = {
thin: 100,
hairline: 100,
extralight: 200,
ultralight: 200,
light: 300,
book: 400,
regular: 400,
normal: 400,
roman: 400,
medium: 500,
semibold: 600,
demibold: 600,
bold: 700,
extrabold: 800,
ultrabold: 800,
heavy: 900,
black: 900
}
1.3 逐层渲染解析
形状处理(布尔运算,旋转变形,蒙版);
样式填充 (描边,阴影,模糊,渐变,着色器);
字体文本渲染;
位图处理。
const LayerTypeMapClass = {
[LAYER_CLASS.TEXT]: Text,
[LAYER_CLASS.RECTANGLE]: Rectangle,
[LAYER_CLASS.STAR]: Star,
[LAYER_CLASS.TRIANGLE]: Triangle,
[LAYER_CLASS.POLYGON]: Polygon,
[LAYER_CLASS.SHAPEPATH]: ShapePath,
[LAYER_CLASS.OVAL]: Oval,
[LAYER_CLASS.SHAPEGROUP]: ShapeGroup,
[LAYER_CLASS.BITMAP]: Bitmap,
[LAYER_CLASS.GROUP]: Group,
[LAYER_CLASS.SYMBOLINSTANCE]: SymbolInstance
[LAYER_CLASS.SLICE]: Slice
}
// 传入图层数据,生成图层数据模型实例
export function generateLayerInstance (data) {
const constructor = LayerTypeMapClass[data._class]
if (constructor) {
const layerInstance = new constructor(data)
return layerInstance
} else {
throw new Error(`Unsupported layer type: ${data._class}`)
}
}
1.4 导出渲染图像内容
screenshotQueue.process(async (job) => {
const { id, page, artboard } = job.data
// 待处理的页面地址
const previewUrl = `${process.env.SCREENSHOT_URL}?id=${id}&page=${page}&artboard=${artboard}`
// 创建browser示例
const browser = await puppeteer.connect({ browserWSEndpoint: 'ws://localhost:8081' })
const tab = await browser.newPage()
tab.setViewport({ width: 200, height: 200, deviceScaleFactor: 2 })
// 打开页面,等待响应
await tab.goto(previewUrl, { waitUntil: 'networkidle0' })
await tab.waitForFunction(`window._STATUS_ !== undefined`, { timeout: 30000 })
// 取得页面截图
const preview = await tab.$('#preview')
await preview.screenshot({ path: `${TARGET_DIR}/${id}/previews/${artboard}.png` })
await tab.close()
return `${TARGET_DIR}/${id}/previews/${artboard}.png`
})
上述方案的确能把成果快速落地,但是在实际使用中,存在CPU、内存占用过高,处理效率低,调用链路复杂等一系列问题,接下来,需要把整套前端处理逻辑迁移至服务端进行实现。
由于这套图像解析方案是基于前端开发模式实现的,对浏览器环境及部分DOM API有较多的依赖,在弃用基于Puppeteer的方案之后,迁移到服务端必须对其内部实现过程进行改造,其中包括:
browser canvas -> node-canvas(基于cario实现);
webgl -> opengles;
html dom, svg -> jsdom;
css -> 移除并改写实现方式。
在服务端渲染改造的时候,遵循以下思路:
拒绝使用基于浏览器环境的渲染处理,如CSS3,document canvas等;
尽量使用成熟的技术,减少试错时间;
素材内容的加载方式改动,本地文件预加载到内存中,不使用http异步获取;
使用基于cario的node-canvas取代puppeteer;
使用基于js-dom的paper.js版本。
var Konva = require('konva');
var canvas = require('canvas'); //node-canvas
// mock window
Konva.window = {
Image: canvas.Image,
devicePixelRatio: 1,
};
// mock document
Konva.document = {
createElement: function () {},
documentElement: {
addEventListener: function () {},
},
};
// make some global injections
global.requestAnimationFrame = (cb) => {
setImmediate(cb);
};
// create canvas in Node env
Konva.Util.createCanvasElement = () => {
const node = new canvas.Canvas();
node.style = {};
return node;
};
// create image in Node env
Konva.Util.createImageElement = () => {
const node = new canvas.Image();
node.style = {};
return node;
};
// _checkVisibility use dom element, in node we can skip it
Konva.Stage.prototype._checkVisibility = () => {};
module.exports = Konva;
效果展示
基于目前对市场上多个在线设计协作工具的技术架构的调研和收集到的资料,未来有几个技术方向值得我们关注:
基于WebAssembly + WebGL的浏览器端图形处理框架及其相关工具集;
搭建基于向量网络的矢量图形编辑工具集;
完全基于SVG的矢量图形处理方案。
布尔逻辑
Node-canvas
Webassembly令Figma处理性能提高了3倍
Path2D API
快乐工作,快乐生活
Happy work , Happy life
/
Join us